#[warn(dead_code)]
use std::ffi::c_void;
use std::option::Option;
use std::os::fd::{BorrowedFd, RawFd};
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use std::{mem::MaybeUninit, ptr};

use gpui::{
    px, rgb, size, AppContext, Bounds, ParentElement, SharedString, Styled, WindowBounds,
};
use libuv_sys2::{
    uv_async_init,
    uv_async_send,
    uv_async_t,
    uv_backend_fd,
    uv_backend_timeout,
    uv_default_loop,
    uv_handle_t,
    uv_loop_t,
    uv_sem_init,
    uv_sem_post,
    uv_sem_t,
    uv_sem_wait,
    uv_thread_create,
    uv_thread_t,
    uv_unref,
    //uv_run
    // uv_run_mode_UV_RUN_NOWAIT
};

use napi::bindgen_prelude::{ClassInstance, External };
use napi::threadsafe_function::ThreadsafeFunction;
use napi::{sys, JsFunction, NapiValue};
use napi::{
    bindgen_prelude::{Buffer, BufferSlice, Function},
    sys::{uv_loop_s, uv_run, uv_run_mode},
    threadsafe_function::ThreadsafeFunctionCallMode,
    CallContext, Env, JsObject, JsUndefined, JsUnknown, Result,
};
use napi_derive::{js_function, napi};

use nix::sys::select::{select, FdSet};
use nix::sys::time::{TimeVal, TimeValLike};

// #[napi]
// fn get_uv_loop(env: Env) -> Result<Buffer> {
//     let mut loop_ptr = std::ptr::null_mut();
//     unsafe {
//         napi_get_uv_event_loop(env.raw(), &mut loop_ptr);
//     }
//     Ok(BufferSlice::from_data(loop_ptr.to_ne_bytes()).into())
// }

struct NodeIntegration {
    uv_loop: *mut uv_loop_t,
    //awake_handle: *mut uv_async_t,
    //embed_sem: *mut uv_sem_t,
    //embed_thread: *mut uv_thread_t,
}

// 确保结构体可安全跨线程
unsafe impl Send for NodeIntegration {}
unsafe impl Sync for NodeIntegration {}

impl NodeIntegration {
    pub fn prepare_message_loop(env: Env) -> Result<Arc<Self>> {
        //let uv_loop = env.get_uv_event_loop().unwrap() as *mut _ as *mut uv_loop_t;
        //let uv_loop: *mut uv_loop_t = unsafe { uv_default_loop() };
        let uv_loop = env.get_uv_event_loop().unwrap() as *mut _ as *mut uv_loop_t;

        //print!("{:#?}", uv_loop);

        // 初始化异步句柄（空回调）
        // let mut awake_handle = MaybeUninit::<uv_async_t>::uninit();
        // unsafe {
        //     uv_async_init(uv_loop, awake_handle.as_mut_ptr(), None);
        //     uv_unref(awake_handle.as_ptr() as *mut uv_handle_t);
        // }

        // // // 初始化信号量
        // let mut embed_sem = MaybeUninit::<uv_sem_t>::uninit();
        // unsafe { uv_sem_init(embed_sem.as_mut_ptr(), 0) };

        // 创建 Arc 实例
        let instance = Arc::new(Self {
            uv_loop,
            //awake_handle: awake_handle.as_mut_ptr(),
            //embed_sem: embed_sem.as_mut_ptr(),
        });

        // 创建 worker 线程
        // let mut embed_thread = MaybeUninit::<uv_thread_t>::uninit();
        // let thread_arg = Arc::into_raw(Arc::clone(&instance)) as *mut c_void;
        // unsafe {
        //     uv_thread_create(
        //         embed_thread.as_mut_ptr(),
        //         Some(Self::embed_thread_runner),
        //         thread_arg,
        //         //ptr::null_mut(),
        //     );
        // }

        Ok(instance)
    }
    // extern "C" fn embed_thread_runner(arg: *mut c_void) {
    //     print!("embed_thread_runner");

    //     // 转换回 Arc 并获取所有权
    //     let instance = unsafe { Arc::from_raw(arg as *const NodeIntegration) };

    //     loop {
    //         print!("tick");
    //         unsafe {
    //             uv_sem_wait(instance.embed_sem);
    //             //uv_async_send(instance.awake_handle);
    //         }
    //     }

    //     // 显式释放 Arc 引用
    //     //drop(instance);
    // }

    pub fn uv_run_once(&self) {
        // 获取事件循环和信号量指针
        let loop_ptr = self.uv_loop as *mut _ as *mut uv_loop_s;
        //let loop_ptr = self.uv_loop;
        //let sem_ptr = self.embed_sem;

        unsafe {
            // 非阻塞运行事件循环
            uv_run(loop_ptr, uv_run_mode::UV_RUN_NOWAIT);
            //uv_run(loop_ptr, uv_run_mode_UV_RUN_NOWAIT);

            // 通知工作线程继续
            //uv_sem_post(sem_ptr);
        }
    }

    // pub fn wakeup_embed_thread(&self) {
    //     unsafe {
    //         uv_async_send(self.awake_handle);
    //     }
    // }

    pub fn poll_events(&self) -> Result<()> {
        unsafe {
            // 获取后端超时时间
            let timeout_ms = uv_backend_timeout(self.uv_loop) as i32;

            // 转换时间格式
            let timeout = if timeout_ms != -1 {
                Some(TimeVal::milliseconds(timeout_ms as i64))
            } else {
                None
            };

            // 获取后端文件描述符
            let fd = uv_backend_fd(self.uv_loop) as RawFd;

            // 初始化文件描述符集合
            let mut read_set = FdSet::new();
            read_set.insert(BorrowedFd::borrow_raw(fd));

            loop {
                print!("测试线程");
                // 执行 select 系统调用
                match select(fd + 1, &mut read_set, None, None, &mut timeout.unwrap()) {
                    Ok(_) => {
                        println!("Event detected");
                        break;
                    }
                    Err(e) if e == nix::Error::EINTR => continue, // 处理中断重试
                    Err(e) => return Err(napi::Error::from_reason(format!("Select error: {}", e))),
                }
            }
        }
        Ok(())
    }

    // pub fn run_message_loop(&self) {
    //     self.uv_run_once();
    // }
}

// extern "C" fn async_callback(handle: *mut uv_async_t) {
//     println!(
//         "Async callback triggered from thread {:?}",
//         std::thread::current().id()
//     );
// }

//unsafe impl Send for Application {}
//unsafe impl Sync for Application {}

#[napi]
pub struct Application {
    inner: Option<gpui::Application>,
    //inner: Arc<Mutex<gpui::Application>>,
    window: Window,
}

#[napi]
impl Application {
    #[napi(constructor)]
    pub fn new() -> Self {
        Application {
            inner: Some(gpui::Application::new()),
            window: Default::default(),
            //inner: Arc::new(Mutex::new(gpui::Application::new())),
        }
    }

    #[napi]
    pub fn create_window(&mut self, options: WindowOptions) -> Window {
        println!("{:#?}", options.title);

        self.window = Window::new(options);

        self.window.clone()
    }

    #[napi]
    pub fn run(&mut self, env: Env) -> Result<()> {
        //pub fn run(&mut self, env: Env, cb: Function<JsCx, ()>) -> Result<()> {
        // let str = "test";
        // let tsfn = cb.build_threadsafe_function().build_callback(move |_| {
        //     //println!("Captured in ThreadsafeFunction"); // str is NULL at this point
        //     Ok(())
        // })?;

        let ni = NodeIntegration::prepare_message_loop(env).unwrap();

        // std::thread::spawn(move || {
        //     let _ = ni.poll_events();
        // });

        // std::thread::spawn(move || {
        //     let _ = ni.poll_events().unwrap();
        // });

        //ni.uv_run_once();

        // let inner_clone = self.inner.clone();
        // std::thread::spawn(move || {
        //     inner_clone.lock().unwrap().run(move |cx| {
        //         println!("Running");
        //     });
        // });

        // let tsfn = cb.create_threadsafe_function(|_| {
        //     Ok(vec![env.get_undefined()?])
        // })?;

        //let tsfn = cb.build_threadsafe_function().build().unwrap();
        // let tsfn = cb
        //     .build_threadsafe_function()
        //     .callee_handled::<true>()
        //     .build()?;

        if let Some(inner) = self.inner.take() {
            let window_options = self.window.options.clone();

            inner.run(move |cx| {
                //println!("{:#?}", &window_options);

                let size = gpui::Size::new(
                    px(window_options.width as f32),
                    px(window_options.height as f32),
                );

                let bounds = Bounds::centered(None, size, cx);

                let titlebar_options = gpui::TitlebarOptions {
                    title: Some(window_options.title.into()),
                    ..Default::default()
                };

                // cx.open_window(
                //     gpui::WindowOptions {
                //         window_bounds: Some(WindowBounds::Windowed(bounds)),
                //         titlebar: Some(titlebar_options),
                //         ..Default::default()
                //     },
                //     |_, cx| {
                //         //cx.new(|_| RootView {
                //             // child:  Some(div()
                //             // .flex()
                //             // .flex_col()
                //             // .gap_3()
                //             // .bg(rgb(0x505050))
                //             // .size(px(500.0)))
                //         //})
                //     },
                // )
                // .unwrap();

                //cx.activate(true);

                // let raw_ptr: *mut gpui::App = cx as *mut gpui::App;
                // let mut owned_app: gpui::App = unsafe { std::ptr::read(raw_ptr) };
                // //let mut owned_app: gpui::App = unsafe { std::mem::transmute_copy(cx) };

                // let bounds = Bounds::centered(None, size(px(500.), px(500.0)), &owned_app);

                // owned_app.open_window(
                //     WindowOptions {
                //         window_bounds: Some(WindowBounds::Windowed(bounds)),
                //         ..Default::default()
                //     },
                //     |_, cx| {

                //         println!("Hello, World!");
                //         cx.new(|_| HelloWorld {
                //             text: "World".into(),
                //         })
                //     },
                // )
                // .unwrap();

                // std::mem::forget(owned_app);

                // let _ = cx
                // .foreground_executor()
                // .spawn(async move {
                //     //println!("Running");
                //     ni.uv_run_once();
                //     // loop {
                //     //     println!("Running");
                //     // }
                // })
                // .detach();

                //let raw_ptr: *mut gpui::App = cx as *mut gpui::App; // 转换为裸指针
                //let owned_app: gpui::App = unsafe { std::ptr::read(raw_ptr) }; // 强制读取指针内容获取所有权

                // //let owned_app: gpui::App = unsafe { std::mem::transmute_copy(cx) }; // 直接拷贝内存
                //let mut js_cx = JsCx::new(owned_app);

                // js_cx.open_window();

                //tsfn.call(js_cx, ThreadsafeFunctionCallMode::NonBlocking);

                //tsfn.call((), ThreadsafeFunctionCallMode::NonBlocking);

                // tsfn.call(Ok(js_cx), ThreadsafeFunctionCallMode::NonBlocking);
                //tsfn.call(js_cx, ThreadsafeFunctionCallMode::NonBlocking);

                //  let bounds = Bounds::centered(None, size(px(500.), px(500.0)), cx);
                //  cx.open_window(
                //      WindowOptions {
                //          window_bounds: Some(WindowBounds::Windowed(bounds)),
                //          ..Default::default()
                //      },
                //      |_, cx| {
                //          cx.new(|_| HelloWorld {
                //              text: "World".into(),
                //          })
                //      },
                //  )
                //  .unwrap();

                //println!("Running");

                // let _ = cx.spawn(|cx| async move {

                //     cx.background_executor().timer(Duration::from_secs(2)).await;
                //     println!("Running");
                //     ni.uv_run_once();
                // }).detach();

                // let _ = cx.background_executor().spawn(async move {
                //     //println!("Running");
                //     ni.uv_run_once();
                //     // loop {
                //     //     println!("Running");
                //     // }

                // }).detach();

                // let mut obj = env.create_object().unwrap();

                // env.create_function("openWindow", |_, _| {
                //     println!("openWindow");
                // });

                // let open_window_fn = Box::new(move || {
                //     // 调用 open_window 方法
                //     let window = cx.foreground_executor().spawn(async move {
                //         print!("test")
                //     });
                // });

                //tsfn.call(open_window_fn, ThreadsafeFunctionCallMode::NonBlocking);

                // let _ = cx
                //     .foreground_executor()
                //     .spawn(async move {
                //         println!("Running");
                //         ni.uv_run_once();
                //     })
                //     .detach();
                //print!("{:#?}", node_integration.uv_loop);

                //node_integration.wakeup_embed_thread();

                //node_integration.wakeup_embed_thread();
            });
        }

        Ok(())
    }
}

// impl Drop for Application {
//     fn drop(&mut self) {
//         self.inner.take().unwrap().quit();
//     }
// }

#[derive(Default, Clone)]
#[napi]
pub struct Window {
    options: WindowOptions,
    //content_view: Option<Div>,
}

#[napi]
impl Window {
    #[napi(constructor)]
    pub fn new(options: WindowOptions) -> Self {
        Window {
            options,
            //content_view: None,
        }
    }

    #[napi(js_name = "setContentView")]
    pub fn set_content_view(&mut self) {
        //self.content_view = Some(view);
    }
}

#[napi(object)]
#[derive(Debug, Default, Clone)]
pub struct WindowOptions {
    pub title: String,
    pub width: i32,
    pub height: i32,
}

#[napi]
pub fn div() -> Div {
    Div::new()
}

#[napi]
pub struct Div {
    inner: gpui::Div,
}

#[napi]
impl Div {

    #[napi(constructor)]
    pub fn new() -> Self {
        Div {
            inner: gpui::div(),
        }
    }
}

// impl FromNapiValue for Div {
//     unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
//         // 手动转换逻辑，例如从指针恢复 Div 实例
//         let mut unknown = JsUnknown::from_raw(env, napi_val)?;
//        // let div: &mut Div = unknown.get_mut()?;
//        // Ok(div.clone())
//     }
// }

// #[napi]
// pub struct JsCx {
//     inner: gpui::App,
// }

// #[napi]
// impl JsCx {
//     pub fn new(app: gpui::App) -> Self {
//         JsCx { inner: app }
//     }

//     #[napi(js_name = "openWindow")]
//     pub fn open_window(&mut self) {
//         let bounds = Bounds::centered(None, size(px(500.), px(500.0)), &self.inner);
//         self.inner
//             .open_window(
//                 WindowOptions {
//                     window_bounds: Some(WindowBounds::Windowed(bounds)),
//                     ..Default::default()
//                 },
//                 |_, cx| {
//                     println!("openWindow");
//                     cx.new(|_| HelloWorld {
//                         text: "World".into(),
//                     })
//                 },
//             )
//             .unwrap();
//     }
// }

// pub fn test(cx: &mut JsCx) {
//     println!("test");
//     cx.open_window();
// }


// #[napi]
// pub fn ele() -> Result<External<gpui::Div>> {
//   Ok(External::new(gpui::div()))
// }

// struct RootView {
//     //child: Option<gpui::Div>,
// }

// impl gpui::Render for RootView {
//     fn render(
//         &mut self,
//         _window: &mut gpui::Window,
//         _cx: &mut gpui::Context<Self>,
//     ) -> impl gpui::IntoElement {
//         div().inner
//     }
// }

// #[napi]
// pub struct App {
//     inner: gpui::App,
// }

// #[napi]
// impl App {
//     pub fn new(cx: gpui::App) -> Self {
//         App { inner: cx, }
//     }

//     #[napi(js_name = "openWindow")]
//     pub fn open_window(&mut self) {
//         print!("openWindow");
//         let bounds = gpui::Bounds::centered(
//             None,
//             gpui::size(gpui::px(500.), gpui::px(500.0)),
//             &self.inner,
//         );

//         self.inner.lock().as_mut()
//             .open_window(
//                 gpui::WindowOptions {
//                     window_bounds: Some(gpui::WindowBounds::Windowed(bounds)),
//                     ..Default::default()
//                 },
//                 |_, cx| {
//                     cx.new(|_| HelloWorld {
//                         text: "World".into(),
//                     })
//                 },
//             )
//             .unwrap();
//     }
// }

//     #[napi(js_name = "openWindow")]
//     pub fn open_window(&mut self) {
//       print!("openWindow");
//       let bounds = gpui::Bounds::centered(None, gpui::size(gpui::px(500.), gpui::px(500.0)), &self.inner);
//       self.inner.open_window(
//         gpui::WindowOptions {
//             window_bounds: Some(gpui::WindowBounds::Windowed(bounds)),
//             ..Default::default()
//         },
//         |_, cx| {
//             cx.new(|_| HelloWorld {
//                 text: "World".into(),
//             })
//         },
//     )
//     .unwrap();
// }
